<?php
namespace ZyucMini\Core;

/**
 * 文件操作类 - 负责文件的读取、写入、删除等操作
 * 提供安全的文件操作功能
 */
class File
{
    /**
     * 读取文件内容
     * 
     * @param string $filePath 文件路径
     * @return string
     * @throws \Exception
     */
    public static function read($filePath)
    {
        self::validatePath($filePath);
        
        if (!file_exists($filePath)) {
            throw new \Exception("ZyucMini\Core\File Error: file not found: $filePath");
        }
        
        if (!is_readable($filePath)) {
            throw new \Exception("ZyucMini\Core\File Error: file not readable: $filePath");
        }
        
        $content = file_get_contents($filePath);
        if ($content === false) {
            throw new \Exception("ZyucMini\Core\File Error: failed to read file: $filePath");
        }
        
        return $content;
    }

    /**
     * 写入内容到文件
     * 
     * @param string $filePath 文件路径
     * @param string $content 文件内容
     * @param int $flags 写入标志
     * @param int $permissions 文件权限
     * @return bool
     * @throws \Exception
     */
    public static function write($filePath, $content, $flags = 0, $permissions = 0644)
    {
        self::validatePath($filePath);
        
        $dir = dirname($filePath);
        if (!is_dir($dir)) {
            if (!mkdir($dir, 0755, true) && !is_dir($dir)) {
                throw new \Exception("ZyucMini\Core\File Error: failed to create directory: $dir");
            }
        }
        
        if (file_put_contents($filePath, $content, $flags) === false) {
            throw new \Exception("ZyucMini\Core\File Error: failed to write to file: $filePath");
        }
        
        // 设置文件权限
        if (!chmod($filePath, $permissions)) {
            throw new \Exception("ZyucMini\Core\File Error: failed to set file permissions: $filePath");
        }
        
        return true;
    }

    /**
     * 删除文件
     * 
     * @param string $filePath 文件路径
     * @return bool
     * @throws \Exception
     */
    public static function delete($filePath)
    {
        self::validatePath($filePath);
        
        if (!file_exists($filePath)) {
            return true;
        }
        
        if (!unlink($filePath)) {
            throw new \Exception("ZyucMini\Core\File Error: failed to delete file: $filePath");
        }
        
        return true;
    }

    /**
     * 检查文件是否存在
     * 
     * @param string $filePath 文件路径
     * @return bool
     */
    public static function exists($filePath)
    {
        return file_exists($filePath);
    }
    
    /**
     * 复制文件
     * 
     * @param string $source 源文件路径
     * @param string $destination 目标文件路径
     * @return bool
     * @throws \Exception
     */
    public static function copy($source, $destination)
    {
        self::validatePath($source);
        self::validatePath($destination);
        
        if (!file_exists($source)) {
            throw new \Exception("ZyucMini\Core\File Error: source file not found: $source");
        }
        
        $dir = dirname($destination);
        if (!is_dir($dir)) {
            if (!mkdir($dir, 0755, true) && !is_dir($dir)) {
                throw new \Exception("ZyucMini\Core\File Error: failed to create directory: $dir");
            }
        }
        
        if (!copy($source, $destination)) {
            throw new \Exception("ZyucMini\Core\File Error: failed to copy file from $source to $destination");
        }
        
        return true;
    }
    
    /**
     * 移动文件
     * 
     * @param string $source 源文件路径
     * @param string $destination 目标文件路径
     * @return bool
     * @throws \Exception
     */
    public static function move($source, $destination)
    {
        self::validatePath($source);
        self::validatePath($destination);
        
        if (!file_exists($source)) {
            throw new \Exception("ZyucMini\Core\File Error: source file not found: $source");
        }
        
        $dir = dirname($destination);
        if (!is_dir($dir)) {
            if (!mkdir($dir, 0755, true) && !is_dir($dir)) {
                throw new \Exception("ZyucMini\Core\File Error: failed to create directory: $dir");
            }
        }
        
        if (!rename($source, $destination)) {
            throw new \Exception("ZyucMini\Core\File Error: failed to move file from $source to $destination");
        }
        
        return true;
    }
    
    /**
     * 获取文件大小
     * 
     * @param string $filePath 文件路径
     * @return int 文件大小(字节)
     * @throws \Exception
     */
    public static function getSize($filePath)
    {
        self::validatePath($filePath);
        
        if (!file_exists($filePath)) {
            throw new \Exception("ZyucMini\Core\File Error: file not found: $filePath");
        }
        
        $size = filesize($filePath);
        if ($size === false) {
            throw new \Exception("ZyucMini\Core\File Error: failed to get file size: $filePath");
        }
        
        return $size;
    }
    
    /**
     * 获取文件信息
     * 
     * @param string $filePath 文件路径
     * @return array 文件信息
     * @throws \Exception
     */
    public static function getInfo($filePath)
    {
        self::validatePath($filePath);
        
        if (!file_exists($filePath)) {
            throw new \Exception("ZyucMini\Core\File Error: file not found: $filePath");
        }
        
        $stat = stat($filePath);
        if ($stat === false) {
            throw new \Exception("ZyucMini\Core\File Error: failed to get file info: $filePath");
        }
        
        return [
            'size' => $stat['size'],
            'mtime' => $stat['mtime'],
            'ctime' => $stat['ctime'],
            'atime' => $stat['atime'],
            'permissions' => $stat['mode'],
            'is_readable' => is_readable($filePath),
            'is_writable' => is_writable($filePath),
            'extension' => pathinfo($filePath, PATHINFO_EXTENSION),
            'basename' => basename($filePath),
            'dirname' => dirname($filePath)
        ];
    }
    
    /**
     * 验证路径安全性
     * 
     * @param string $path 路径
     * @throws \Exception
     */
    protected static function validatePath($path)
    {
        if (empty($path)) {
            throw new \Exception("ZyucMini\Core\File Error: path cannot be empty");
        }
        
        // 检查路径遍历攻击
        if (strpos($path, '..') !== false) {
            throw new \Exception("ZyucMini\Core\File Error: path traversal detected in: $path");
        }
        
        // 检查绝对路径长度
        $realPath = realpath(dirname($path));
        if ($realPath === false) {
            throw new \Exception("ZyucMini\Core\File Error: invalid path: $path");
        }
    }
}
?>